﻿using Link_eLab.SqlSugar.Extension;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Configuration.ServerApi.Dao;
using Configuration.ServerApi.Entity;
using Configuration.ServerApi.Entity.Model;
using Configuration.ServerApi.Param;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Configuration.ServerApi.Service.Impl
{
    /// <summary>
    /// MenuService
    /// </summary>
    public class MenuService : IMenuService
    {
        private readonly IConfiguration Configuration;
        private readonly IHttpContextAccessor Accessor;
        private readonly ISysMenuDao SysMenuDao;
        private readonly ISysRoleMenuDao SysRoleMenuDao;

        #region 构造函数

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="accessor"></param>
        /// <param name="sysMenuDao"></param>
        /// <param name="sysRoleMenuDao"></param>
        public MenuService(IConfiguration configuration,
            IHttpContextAccessor accessor,
            ISysMenuDao sysMenuDao,
            ISysRoleMenuDao sysRoleMenuDao)
        {
            Configuration = configuration;
            Accessor = accessor;
            SysMenuDao = sysMenuDao;
            SysRoleMenuDao = sysRoleMenuDao;
        }

        #endregion 构造函数

        #region 自定义方法

        #region 获取子级菜单数据

        /// <summary>
        /// 获取子级菜单数据
        /// </summary>
        /// <param name="allMenuData">菜单数据源</param>
        /// <param name="parentId">所属父级ID</param>
        /// <returns>处理后的数据</returns>
        private List<TreeDataModel> GetChildren(List<sys_menu> allMenuData, string parentId)
        {
            List<TreeDataModel> menus;
            List<sys_menu> subMenus = allMenuData.Where(w => w.ParentId.Equals(parentId)).ToList();
            if (subMenus != null && subMenus.Count() > 0)
            {
                menus = new List<TreeDataModel>();
                foreach (var item in subMenus)
                {
                    menus.Add(new TreeDataModel
                    {
                        Id = item.Id,
                        Label = item.Title,
                        Children = GetChildren(allMenuData, item.Id)
                    });
                }
            }
            else
            {
                return new List<TreeDataModel>();
            }
            return menus;
        }

        /// <summary>
        /// 获取子级菜单数据
        /// </summary>
        /// <param name="allMenuData">菜单数据源</param>
        /// <param name="parentId">所属父级ID</param>
        /// <returns>处理后的数据</returns>
        private List<MenuModel> GetMenuChildren(List<sys_menu> allMenuData, string parentId)
        {
            List<MenuModel> menus;
            List<sys_menu> subMenus = allMenuData.Where(w => w.ParentId.Equals(parentId)).ToList();
            if (subMenus != null && subMenus.Count() > 0)
            {
                menus = new List<MenuModel>();
                foreach (var item in subMenus)
                {
                    menus.Add(new MenuModel
                    {
                        Id = item.Id,
                        Icon = item.Icon,
                        Name = item.Name,
                        Title = item.Title,
                        Path = item.Path,
                        Component = item.Component,
                        Redirect = item.Redirect,
                        Hidden = item.Hidden,
                        ParentId = item.ParentId,
                        AlwaysShow = item.AlwaysShow,
                        Children = GetMenuChildren(allMenuData, item.Id)
                    });
                }
            }
            else
            {
                return new List<MenuModel>();
            }
            return menus;
        }

        #endregion

        #endregion

        #region 获取菜单列表

        /// <summary>
        /// 获取菜单列表
        /// </summary>
        /// <param name="param">搜索条件</param>
        /// <returns>JSON结果集</returns>
        public async Task<JsonResult> MenuList(SearchModel param)
        {
            Console.WriteLine("\n获取菜单列表：MenuList");

            #region 获取登录用户相关信息

            string orgId = string.Empty;
            string userId = string.Empty;
            string userRoleId = string.Empty;
            try
            {
                orgId = Accessor.HttpContext.User.Claims.First(i => i.Type == "orgId").Value;
                userId = Accessor.HttpContext.User.Claims.First(i => i.Type == "userId").Value;
                userRoleId = Accessor.HttpContext.User.Claims.First(i => i.Type == "userRoleId").Value;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return new JsonResult(new ResultModel
                {
                    Success = false,
                    Msg = "Token已过期, 请重新登录"
                });
            }

            #endregion

            // 初始化数据查询表达式
            Expression<Func<sys_menu, bool>> expression = w => w.Del_Flag == 0;

            Console.WriteLine($"Name：{param.Name}");
            if (!string.IsNullOrEmpty(param.Name))
            {
                expression = expression.And(w => w.Name.Contains(param.Name));
            }

            dynamic result = null;
            if (param.Page != null && param.Limit != null)
            {
                result = await SysMenuDao.QueryByWherePage(param.Page.Value, param.Limit.Value, expression, o => o.Sort);
            }
            else
            {
                result = await SysMenuDao.QueryByWhere(expression, o => o.Sort);
            }
            var count = await SysMenuDao.QueryCount(expression);

            return new JsonResult(new ResultModel
            {
                Count = count,
                Data = result
            });
        }

        #endregion

        #region 获取菜单详情

        /// <summary>
        /// 获取菜单详情
        /// </summary>
        /// <param name="param">搜索条件</param>
        /// <returns>JSON结果集</returns>
        public async Task<JsonResult> MenuDetail(SearchModel param)
        {
            Console.WriteLine("\n获取菜单详情：MenuDetail");

            #region 参数校验

            Console.WriteLine($"Id：{param.Id}");
            if (string.IsNullOrEmpty(param.Id))
            {
                return new JsonResult(new ResultModel
                {
                    Success = false,
                    Msg = "必填参数不能为空"
                });
            }

            #endregion

            return new JsonResult(new ResultModel
            {
                Data = await SysMenuDao.QuerySingle(w => w.Del_Flag == 0 && w.Id.Equals(param.Id))
            });
        }

        #endregion

        #region 提交菜单信息

        /// <summary>
        /// 提交菜单信息
        /// </summary>
        /// <param name="param">更新参数集</param>
        /// <returns>JSON结果集</returns>
        public async Task<JsonResult> SubmitMenu(UpdateModel param)
        {
            Console.WriteLine("\n提交菜单信息：SubmitMenu");

            #region 参数、数据校验

            Console.WriteLine($"Id：{param.MenuData.Id}");

            if (string.IsNullOrEmpty(param.MenuData.Name))
            {
                return new JsonResult(new ResultModel
                {
                    Success = false,
                    Msg = "必填参数不能为空"
                });
            }

            #endregion 

            #region 数据提交

            DateTime now = DateTime.Now;
            Guid guid = Guid.NewGuid();
            string newId = guid.ToString().ToUpper();

            int result = 0;

            // 如果Guid为空时则新增，否则为编辑
            if (string.IsNullOrEmpty(param.MenuData.Id))
            {
                var model = new sys_menu()
                {
                    Id = newId,
                    Type = param.MenuData.Type,
                    Name = param.MenuData.Name,
                    Path = param.MenuData.Path,
                    Component = param.MenuData.Component,
                    Redirect = param.MenuData.Redirect,
                    Title = param.MenuData.Title,
                    Icon = param.MenuData.Icon,
                    ParentId = param.MenuData.ParentId,
                    Sort = param.MenuData.Sort,
                    Hidden = param.MenuData.Hidden,
                    AlwaysShow = param.MenuData.AlwaysShow,
                    Remark = param.MenuData.Remark,
                    CreateTime = now,
                    Del_Flag = 0
                };
                result = await SysMenuDao.Insert(model);

                return new JsonResult(new ResultModel
                {
                    Msg = "新增成功"
                });
            }
            else
            {
                result = SysMenuDao.Update(u => new sys_menu()
                {
                    Type = param.MenuData.Type,
                    Name = param.MenuData.Name,
                    Path = param.MenuData.Path,
                    Component = param.MenuData.Component,
                    Redirect = param.MenuData.Redirect,
                    Title = param.MenuData.Title,
                    Icon = param.MenuData.Icon,
                    ParentId = param.MenuData.ParentId,
                    Sort = param.MenuData.Sort,
                    Hidden = param.MenuData.Hidden,
                    AlwaysShow = param.MenuData.AlwaysShow,
                    Remark = param.MenuData.Remark,
                }, w => w.Id.Equals(param.MenuData.Id)).Result;

                return new JsonResult(new ResultModel
                {
                    Msg = "编辑成功"
                });
            }

            #endregion 数据提交
        }

        #endregion

        #region 批量删除菜单信息

        /// <summary>
        /// 批量删除菜单信息
        /// </summary>
        /// <param name="param">更新参数集</param>
        /// <returns>JSON结果集</returns>
        public async Task<JsonResult> DelMenu(UpdateModel param)
        {
            Console.WriteLine("\n批量删除菜单信息：DelMenu");

            #region 参数效验

            Console.WriteLine($"Id：{param.Id}");

            if (string.IsNullOrEmpty(param.Id))
            {
                return new JsonResult(new ResultModel
                {
                    Success = false,
                    Msg = "必填参数不能为空"
                });
            }

            #endregion

            #region 获取登录用户相关信息

            string userId = string.Empty;
            string userName = string.Empty;
            try
            {
                userId = Accessor.HttpContext.User.Claims.First(i => i.Type == "userId").Value;
                userName = Accessor.HttpContext.User.Claims.First(i => i.Type == "userName").Value;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return new JsonResult(new ResultModel
                {
                    Success = false,
                    Msg = "Token已过期, 请重新登录"
                });
            }

            #endregion

            string[] idArray = param.Id.Split(',');

            int result = 0;
            foreach (var item in idArray)
            {
                Console.WriteLine(item);
                result += await SysMenuDao.Update(u => new sys_menu
                {
                    Del_Flag = 1
                }, w => w.Id.Equals(item));
            }

            return new JsonResult(new ResultModel
            {
                Msg = "删除成功",
                Data = result
            });
        }

        #endregion

        #region 获取树形菜单列表

        /// <summary>
        /// 获取树形菜单列表
        /// </summary>
        /// <returns>JSON结果集</returns>
        public async Task<JsonResult> TreeMenuList()
        {
            Console.WriteLine("\n获取树形菜单列表：TreeMenuList");

            #region 获取登录用户相关信息

            string orgId = string.Empty;
            string userId = string.Empty;
            string userRoleId = string.Empty;
            try
            {
                orgId = Accessor.HttpContext.User.Claims.First(i => i.Type == "orgId").Value;
                userId = Accessor.HttpContext.User.Claims.First(i => i.Type == "userId").Value;
                userRoleId = Accessor.HttpContext.User.Claims.First(i => i.Type == "userRoleId").Value;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return new JsonResult(new ResultModel
                {
                    Success = false,
                    Msg = "Token已过期, 请重新登录"
                });
            }

            #endregion

            // 获取全部菜单数据
            var MenuData = await SysMenuDao.QueryByWhere(w => w.Del_Flag == 0 && "false".Equals(w.Hidden), o => o.Sort);

            // 存储转换好的返回数据
            List<TreeDataModel> result = new List<TreeDataModel>();

            // 获取一级菜单数据
            List<sys_menu> FirstLevelMenuData = MenuData.Where(w => "0".Equals(w.ParentId)).ToList();

            FirstLevelMenuData.ForEach(item =>
            {
                result.Add(new TreeDataModel()
                {
                    Id = item.Id,
                    Label = item.Title,
                    Children = GetChildren(MenuData, item.Id)
                });
            });

            return new JsonResult(new ResultModel
            {
                Data = result
            });
        }

        #endregion

        #region 获取全部树形菜单节点列表

        /// <summary>
        /// 获取全部树形菜单节点列表
        /// </summary>
        /// <returns>JSON结果集</returns>
        public async Task<JsonResult> AllTreeMenuNodeList()
        {
            Console.WriteLine("\n获取全部树形菜单节点列表：AllTreeMenuNodeList");

            #region 获取登录用户相关信息

            string orgId = string.Empty;
            string userId = string.Empty;
            string userRoleId = string.Empty;
            try
            {
                orgId = Accessor.HttpContext.User.Claims.First(i => i.Type == "orgId").Value;
                userId = Accessor.HttpContext.User.Claims.First(i => i.Type == "userId").Value;
                userRoleId = Accessor.HttpContext.User.Claims.First(i => i.Type == "userRoleId").Value;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return new JsonResult(new ResultModel
                {
                    Success = false,
                    Msg = "Token已过期, 请重新登录"
                });
            }

            #endregion

            // 获取全部菜单数据
            var MenuData = await SysMenuDao.QueryByWhere(w => w.Del_Flag == 0 && "false".Equals(w.Hidden), o => o.Sort);

            // 存储转换好的返回数据
            List<TreeDataModel> result = new List<TreeDataModel>();

            MenuData.ForEach(item =>
            {
                result.Add(new TreeDataModel()
                {
                    Id = item.Id,
                    Label = item.Title,
                    Children = GetChildren(MenuData, item.Id)
                });
            });

            return new JsonResult(new ResultModel
            {
                Data = result
            });
        }

        #endregion

        #region 获取登录用户拥有的权限菜单列表

        /// <summary>
        /// 获取登录用户拥有的权限菜单列表
        /// </summary>
        /// <returns>JSON结果集</returns>
        public async Task<JsonResult> UserRoleMenuList()
        {
            Console.WriteLine("\n获取登录用户拥有的权限菜单列表：UserRoleMenuList");

            #region 获取登录用户相关信息

            string orgId = string.Empty;
            string userId = string.Empty;
            string userRoleId = string.Empty;
            try
            {
                orgId = Accessor.HttpContext.User.Claims.First(i => i.Type == "orgId").Value;
                userId = Accessor.HttpContext.User.Claims.First(i => i.Type == "userId").Value;
                userRoleId = Accessor.HttpContext.User.Claims.First(i => i.Type == "userRoleId").Value;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return new JsonResult(new ResultModel
                {
                    Success = false,
                    Msg = "Token已过期, 请重新登录"
                });
            }

            #endregion

            List<sys_role_menu> RoleAuthData = new List<sys_role_menu>();

            // 系统管理员获取全部权限菜单数据
            if ("0".Equals(userRoleId))
            {
                RoleAuthData = await SysRoleMenuDao.QueryAll();
            }
            else
            {
                // 获取登录用户的角色拥有的权限菜单数据
                RoleAuthData = await SysRoleMenuDao.QueryByWhere(w => userRoleId.Equals(w.RoleId));
                if (RoleAuthData == null || RoleAuthData.Count <= 0)
                {
                    return new JsonResult(new ResultModel
                    {
                        Success = false,
                        Msg = "此角色暂无菜单权限"
                    });
                }
            }
            List<string> RoleMenuIds = RoleAuthData.Select(s => s.MenuId).ToList();

            // 初始化数据查询表达式
            Expression<Func<sys_menu, bool>> expression = w => w.Del_Flag == 0 && ("true".Equals(w.Hidden) || RoleMenuIds.Contains(w.Id));

            var result = await SysMenuDao.QueryByWhere(expression, o => o.Sort);
            var count = await SysMenuDao.QueryCount(expression);

            return new JsonResult(new ResultModel
            {
                Count = count,
                Data = result,
                Data2 = result.Where(w => !"true".Equals(w.Hidden)).Select(s => s.Id).ToArray()
            });
        }

        #endregion

        #region 获取登录用户拥有的树形权限菜单列表

        /// <summary>
        /// 获取登录用户拥有的树形权限菜单列表
        /// </summary>
        /// <returns>JSON结果集</returns>
        public async Task<JsonResult> UserRoleTreeMenuList()
        {
            Console.WriteLine("\n获取登录用户拥有的树形权限菜单列表：UserRoleTreeMenuList");

            #region 获取登录用户相关信息

            string orgId = string.Empty;
            string userId = string.Empty;
            string userRoleId = string.Empty;
            try
            {
                orgId = Accessor.HttpContext.User.Claims.First(i => i.Type == "orgId").Value;
                userId = Accessor.HttpContext.User.Claims.First(i => i.Type == "userId").Value;
                userRoleId = Accessor.HttpContext.User.Claims.First(i => i.Type == "userRoleId").Value;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return new JsonResult(new ResultModel
                {
                    Success = false,
                    Msg = "Token已过期, 请重新登录"
                });
            }

            #endregion

            // 获取登录用户的角色拥有的权限菜单数据
            List<sys_role_menu> RoleAuthData = await SysRoleMenuDao.QueryByWhere(w => userRoleId.Equals(w.RoleId));
            if (RoleAuthData == null || RoleAuthData.Count <= 0)
            {
                return new JsonResult(new ResultModel
                {
                    Success = false,
                    Msg = "此角色暂无菜单权限"
                });
            }
            List<string> RoleMenuIds = RoleAuthData.Select(s => s.MenuId).ToList();

            // 初始化数据查询表达式
            Expression<Func<sys_menu, bool>> expression = w => w.Del_Flag == 0 && ("true".Equals(w.Hidden) || RoleMenuIds.Contains(w.Id));

            // 获取全部菜单数据
            var MenuData = await SysMenuDao.QueryByWhere(expression, o => o.Sort);

            // 存储转换好的返回数据
            List<MenuModel> result = new List<MenuModel>();

            // 获取一级菜单数据
            List<sys_menu> FirstLevelMenuData = MenuData.Where(w => "0".Equals(w.ParentId)).ToList();

            FirstLevelMenuData.ForEach(item =>
            {
                result.Add(new MenuModel()
                {
                    Id = item.Id,
                    Icon = item.Icon,
                    Name = item.Name,
                    Title = item.Title,
                    Path = item.Path,
                    Component = item.Component,
                    Redirect = item.Redirect,
                    Hidden = item.Hidden,
                    ParentId = item.ParentId,
                    AlwaysShow = item.AlwaysShow,
                    Children = GetMenuChildren(MenuData, item.Id)
                });
            });

            return new JsonResult(new ResultModel
            {
                Data = result
            });
        }

        #endregion

        #region 获取指定角色拥有的权限菜单列表

        /// <summary>
        /// 获取指定角色拥有的权限菜单列表
        /// </summary>
        /// <param name="param">搜索条件</param>
        /// <returns>JSON结果集</returns>
        public async Task<JsonResult> UserRoleMenuListById(SearchModel param)
        {
            Console.WriteLine("\n获取指定角色拥有的权限菜单列表：UserRoleMenuListById");

            #region 参数校验

            Console.WriteLine($"Id：{param.Id}");
            if (string.IsNullOrEmpty(param.Id))
            {
                return new JsonResult(new ResultModel
                {
                    Success = false,
                    Msg = "必填参数不能为空"
                });
            }

            #endregion

            // 获取登录用户的角色拥有的权限菜单数据
            List<sys_role_menu> RoleAuthData = await SysRoleMenuDao.QueryByWhere(w => param.Id.Equals(w.RoleId));
            if (RoleAuthData == null || RoleAuthData.Count <= 0)
            {
                return new JsonResult(new ResultModel
                {
                    Success = false,
                    Msg = "此角色暂无菜单权限"
                });
            }
            List<string> RoleMenuIds = RoleAuthData.Select(s => s.MenuId).ToList();

            // 初始化数据查询表达式
            Expression<Func<sys_menu, bool>> expression = w => w.Del_Flag == 0 && ("true".Equals(w.Hidden) || RoleMenuIds.Contains(w.Id));

            var result = await SysMenuDao.QueryByWhere(expression, o => o.Sort);
            var count = await SysMenuDao.QueryCount(expression);

            return new JsonResult(new ResultModel
            {
                Count = count,
                Data = result,
                Data2 = result.Where(w => !"true".Equals(w.Hidden)).Select(s => s.Id).ToArray()
            });
        }

        #endregion

        #region 提交角色菜单授权信息

        /// <summary>
        /// 提交角色菜单授权信息
        /// </summary>
        /// <param name="param">更新参数集</param>
        /// <returns>JSON结果集</returns>
        public async Task<JsonResult> SubmitUserRoleMenu(UpdateModel param)
        {
            Console.WriteLine("\n提交角色菜单授权信息：SubmitUserRoleMenu");

            #region 参数、数据校验

            Console.WriteLine($"Id：{param.Id}");
            Console.WriteLine($"MenuIds：{param.MenuIds}");

            if (string.IsNullOrEmpty(param.Id))
            {
                return new JsonResult(new ResultModel
                {
                    Success = false,
                    Msg = "必填参数不能为空"
                });
            }

            #endregion

            #region 数据提交

            DateTime now = DateTime.Now;
            string[] idArray = param.MenuIds.Split(',');

            List<sys_role_menu> data = new List<sys_role_menu>();

            // 删除原始数据
            int delData = await SysRoleMenuDao.Delete(w => w.RoleId.Equals(param.Id));

            // 填充用户传递的数据
            foreach (var item in idArray)
            {
                data.Add(new sys_role_menu()
                {
                    RoleId = param.Id,
                    MenuId = item,
                    CreateTime = now
                });
            }

            // 新增数据
            int result = await SysRoleMenuDao.InsertMany(data);

            return new JsonResult(new ResultModel
            {
                Msg = "角色授权更新成功",
                Data = result
            });

            #endregion 数据提交
        }

        #endregion

    }
}